#include "memorymanager.h"
#include "memoryalloc.h"
#include "error.h"
#include "..\common\types.h"
#include "..\common\string.h"

#include "..\common\util.h"
#include <stdio.h>

void MemoryManager::InsertBlock(Block *pBlock)
{
	if(pHead == NULL)
	{
		pHead = pBlock; 
		pHead->Prev = NULL; 
		pHead->Next = NULL; 
		pPrev = pHead; 
	}
	else
	{
		pPrev->Next = pBlock; 
		pBlock->Prev = pPrev; 
		pPrev = pBlock; 
		pBlock->Next = NULL; 
	}
}

void MemoryManager::RemoveBlock(Block *pBlock)
{
	if(pHead != NULL)
	{
		for(Block* pCurrent = pHead;  pCurrent;  pCurrent = pCurrent->Next)
		{
			if(pCurrent == pBlock)
			{
				if(pCurrent->Prev)
					pCurrent->Prev->Next = pCurrent->Next; 
				else
					pHead = pCurrent->Next; 

				if(pCurrent->Next)
				{
					if(pCurrent->Prev == NULL)
						pHead = pCurrent->Next; 
					pCurrent->Next->Prev = pCurrent->Prev; 
				}
				else if(pCurrent->Prev)
					pCurrent->Prev->Next = NULL; 
				return; 
			}
		}
	}
}

void MemoryManager::GetMemoryReport(string &report)
{
	char buffer[MAX_PATH] = {0}; 

	sprintf_s(buffer, sizeof(char) * MAX_PATH, "Allocation:\nCalls: %i\nBytes: %i\n\nDeallocation:\nCalls: %i\nBytes: %i\n\nLeakage:\nBytes: %i\n",
		mAllocationCount, mAllocatedBytes, mDeallocationCount, mDeallocatedBytes, mAllocatedBytes - mDeallocatedBytes); 

	report = string(buffer); 
}

void* MemoryManager::Allocate(size_t size, bool isArray, const char* file, unsigned int line)
{
	if(size == 0)
	{
		#ifdef DEBUG_MEMORYMANAGER
		CError::CError("Invalid memory allocation request\n", line, file); 
		#else
		CError::LogError("Invalid memory allocation request\n"); 
		#endif
		return NULL; 
	}

	size_t uiExtendedSize = /*sizeof(MemoryManager::Block) + */size; 
	char* pAddr = (char*)malloc(uiExtendedSize); 

	/*MemoryManager::Block* pBlock = (Block*)pAddr; 

	pBlock->File = 0; file; 
	pBlock->IsArray = isArray; 
	pBlock->Line = line; 
	pBlock->Size = size; 
	
	InsertBlock(pBlock); 

	mAllocationCount ++; 
	mAllocatedBytes += size; 

	pAddr += sizeof(Block); */
	return (void*)pAddr; 
}

void MemoryManager::Deallocate(char *pAddr, bool isArray)
{
	if(pAddr == NULL)
	{
		CError::CError("Invalid memory deallocation request\n"); 
		return; 
	}

	/*pAddr -= sizeof(MemoryManager::Block); */
	MemoryManager::Block* pBlock = (MemoryManager::Block*)pAddr; 

	/*if(pBlock->Size == 0)
	{			
		string error("Invalid memory block size found during deallocation request\n"); 
		error.concat(CUtil::toString(pBlock->Line)); 
		CError::LogError(error); 
		return; 
	}

	if(pBlock->IsArray != isArray)
	{
		CError::LogError("Block array mismatch detected during deallocation request\n"); 
		return; 
	}		

	
	mDeallocationCount ++; 
	mDeallocatedBytes += pBlock->Size; 
	
	RemoveBlock(pBlock); */

	free(pAddr); 
}

MemoryManager::Block* MemoryManager::pHead = NULL;  
MemoryManager::Block* MemoryManager::pPrev = NULL;  
unsigned int MemoryManager::mAllocationCount = 0; 
unsigned int MemoryManager::mDeallocationCount = 0; 

unsigned int MemoryManager::mAllocatedBytes = 0; 
unsigned int MemoryManager::mDeallocatedBytes = 0; 
